package com.ebor.utils.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpConnectionManager;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * HTTP请求工具
 * @author C
 */
@Slf4j
public class Http {
    /** 连接等待30秒 */
    public static final int CON_TIMEOUT = 30000;
    /** 响应等待10秒 */
    public static final int SO_TIMEOUT = 10000;


    /**
     * POST(JSON)
     */
    public static String post(String url, JSONObject params, Logger logger) {
        return post(url, params, null, logger);
    }

    /**
     * POST(file)
     */
    public static String post(String url, InputStream is, String fileName, Logger logger) {
        return post(url, new HashMap<>(), new HashMap<>(), is, fileName, logger);
    }

    /**
     * POST(file)
     */
    public static String post(String url, Map<String, String> header, Map<String,String> param, InputStream is, String fileName, Logger logger) {
        String responseJsonString = "";
        CloseableHttpClient httpClient = null;
        try {
            MultipartEntityBuilder builder = MultipartEntityBuilder.create().setMode(HttpMultipartMode.RFC6532);
            // 把文件加到HTTP的post请求中
            builder.addBinaryBody("files", is, ContentType.MULTIPART_FORM_DATA, fileName);
            for(Map.Entry<String, String> entry : param.entrySet()) {
                builder.addTextBody(entry.getKey(), entry.getValue());
            }
            HttpPost httpPost = new HttpPost(url);
            for(Map.Entry<String, String> entry : header.entrySet()) {
                httpPost.setHeader(entry.getKey(), entry.getValue());
            }
            httpPost.setEntity(builder.build());
            httpClient = HttpClients.createDefault();
            CloseableHttpResponse response = httpClient.execute(httpPost);
            HttpEntity responseEntity = response.getEntity();
            responseJsonString = EntityUtils.toString(responseEntity, "UTF-8");
            logger.info("POST：{}\theader:{}\trequest:{}\tresponse:{}", url, header, param, responseJsonString);
        } catch (Exception e) {
            logger.error("POST：{}\theader:{}\trequest:{}\ts response:{}",url, header, param, responseJsonString, e);
        } finally {
            if (null != httpClient) {
                try {
                    httpClient.close();
                } catch (IOException e) {
                    log.error("调用上传文件接口流关闭失败{}", e.getMessage(), e);
                }
            }
        }
        return responseJsonString;
    }

    /**
     * POST(JSON)
     */
    public static String post(String url, JSONObject json, ResultHandler handler, Logger logger) {
        String result = null;
        PostMethod postMethod = null;
        try {
            HttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
            manager.getParams().setConnectionTimeout(CON_TIMEOUT);
            manager.getParams().setSoTimeout(SO_TIMEOUT);
            HttpClient httpclient = new HttpClient(manager);
            postMethod = new PostMethod(url);
            RequestEntity se = new StringRequestEntity(json.toString(), "application/json", "UTF-8");
            postMethod.setRequestEntity(se);
            int statusCode = httpclient.executeMethod(postMethod);
            String charSet =  postMethod.getResponseCharSet();
            result = new String(postMethod.getResponseBodyAsString().getBytes(charSet), StandardCharsets.UTF_8);
            if(handler!=null){
                handler.handle(statusCode, result);
            }
            logger.info("POST：{} request:{}\tcharSet:{} statusCode:{} response:{}",url,json,charSet,statusCode,result);
        } catch (Exception e) {
            if(handler!=null){
                handler.handle(-1, e.toString());
            }
            logger.error("POST：{} request:{}\ts response:{}",url,json,result,e);
        } finally {
            if (postMethod != null) {
                postMethod.releaseConnection();
            }
        }
        return result;
    }

    /**
     * POST(STR)
     */
    public static String post(String url, String req, ResultHandler handler, Logger logger) {
        String result = null;
        PostMethod postMethod = null;
        long beginTime = System.currentTimeMillis();
        try {
            HttpConnectionManager manager = new MultiThreadedHttpConnectionManager();
            manager.getParams().setConnectionTimeout(CON_TIMEOUT);
            manager.getParams().setSoTimeout(SO_TIMEOUT);
            HttpClient httpclient = new HttpClient(manager);
            postMethod = new PostMethod(url);
            RequestEntity se = new StringRequestEntity(req, "text/plain", "UTF-8");
            postMethod.setRequestEntity(se);
            int statusCode = httpclient.executeMethod(postMethod);
            InputStream inputStream = postMethod.getResponseBodyAsStream();
            String charSet = postMethod.getResponseCharSet();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            StringBuilder stringBuffer = new StringBuilder();
            String str= "";
            while((str = br.readLine()) != null){
                stringBuffer .append(str );
            }
            result = stringBuffer.toString();
            if (handler != null) {
                handler.handle(statusCode, result);
            }
            logger.info("POST:{}\trequest:{}\tcharSet:{}\tstatusCode:{}\tresponse:{}\telapsedTime:{}", url, req, charSet, statusCode, result, elapsedTime(beginTime));
        } catch (Exception e) {
            if (handler != null) {
                handler.handle(-1, e.toString());
            }
            logger.error("POST:{}\trequest:{}\t\tresponse:{}\telapsedTime:{}", url, req, result, elapsedTime(beginTime), e);
        } finally {
            if (postMethod != null) {
                postMethod.releaseConnection();
            }
        }
        return result;
    }

    public static String elapsedTime(long beginTime) {
        long endTime = System.currentTimeMillis();
        return (endTime - beginTime) + "ms";
    }
}